-- matrix multiplication in parallel/distributed using lua/aLua
-- to execute type: lua mult.lua


-- configuration area 

-- Please define the disponible hosts and ports to execute this program 
addrs = { 
		{addr = "127.0.0.1", port=6080},
		{addr = "127.0.0.1", port=6081},
		{addr = "127.0.0.1", port=6082},
		{addr = "127.0.0.1", port=6083},
		{addr = "127.0.0.1", port=6084}

	}


-- define a size of matrix 
tam = 100


-- begin of implementation
require("alua")

count = 1 -- generic... just initialize their
nodes = {} -- declare as vector, will recive addrs

-- matrix initialize procedures, theirs strings will be passed to hosts to process
-- note that command to send must be a string, and "tam" variable for example is 
-- concatenated to your value
mat1Define = [[
	mat1 = {}
	tam =]]..tam..[[
	for i=1,tam do
		mat1[i] = {}
		for j=1,tam,1 do
			mat1[i][j]= i
		end	
	end
]]


mat2Define = [[
	mat2 = {}
	tam =]]..tam..[[
	for i=1,tam do
		mat2[i] = {}
		for j=1,tam do
			mat2[i][j] = j
		end
	end
]]

mat3Define = [[
	mat3 = {}
	tam =]]..tam..[[
	for i=1, tam do
		mat3[i] = {}
		for j=1, tam do
			mat3[i][j] = 0
		end
	end
]]

function sendcb(reply)
   for id, msg in pairs(reply) do
     if msg.status == "ok" then
       print("Message received and executed by " .. id)
     else
       print("Process " .. id .. " could not receive or execute the message")
       print("Error: " .. msg.error)
     end
   end
end

function spawn_mat1Define(reply)
	for proc, resp in pairs(reply.processes) do
		if resp.status == "ok" then
			alua.send(proc,mat1Define, sendcb)
		end
	end
end

function spawn_mat2Define(reply)
	for proc, resp in pairs(reply.processes) do
		if resp.status == "ok" then
			alua.send(proc,mat2Define, sendcb)
		end
	end
end

function spawn_mat3Define(reply)
	for proc, resp in pairs(reply.processes) do
		if resp.status == "ok" then
			alua.send(proc,mat3Define, sendcb)
		end
	end
end

function nodeslinked(reply)
	print("on link callback:"..reply.status)
	-- now all nodes are linked,is time to silece my problem ...
	alua.spawn(1, spawn_mat1Define)
	alua.spawn(1, spawn_mat2Define)
	alua.spawn(1, spawn_mat3Define)
	--alua.spawn(cntrow(m1), spawn_solve)
 
end


-- this function allow a message passing between nodes
-- and set as callback nodeslinked function
function linknodes(reply)
	print("on open: "..reply.status)
	alua.link(nodes[1],nodedflinked)
end


-- this (recursive) function create daemons, and open theirs
-- pass "linknodes" as callback function
function createnodes()
   if count <= #addrs then
      alua.create(addrs[count], createnodes)
   else
      alua.open(nodes[1], linknodes)
   end
end



-- the main function
function runprogram()

	print("Running ...");

	-- loop around addrs (table) and copy theirs values to nodes
	-- nodes must recive "127.0.0.1:3040" format for each line
	while count <= #addrs do
		nodes[count] = addrs[count].addr..":"..addrs[count].port
		count = count + 1
	end
	
	-- now, the requied variables is ok, alloc a nodes
	createnodes()

	-- run alua events
	alua.loop()
end


-- run a program
runprogram()


